package org.xlp.db.xml;

import org.xlp.db.sql.PagedSQL;
import org.xlp.db.sql.Statistics;
import org.xlp.db.sql.limit.Limit;
import org.xlp.db.utils.SQLUtil;
import org.xlp.db.xml.ele.SQLEle;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Description: Oracle Sql处理类
 * <br/>date: 2025/3/29
 *
 * @version 1.0
 * @author: xlp
 */
public class XmlSQLForOracle extends XmlSQL implements PagedSQL {
    /**
     * 存储分页信息
     */
    private Limit limit;

    /**
     * 当SQLEle中的ParamEle对象为null时，即在xml文件中没param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param cs     实体类型
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, Object[] params, Class<?> cs) {
        super(sqlEle, params, cs);
    }

    /**
     * 当SQLEle中的ParamEle对象为null时，即在xml文件中没param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, Object[] params) {
        super(sqlEle, params);
    }

    /**
     * 当SQLEle中的ParamEle对象为null时，即在xml文件中没param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param cs     实体类型
     * @throws NullPointerException 假如参数sqlEle或params为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, List<Object> params, Class<?> cs) {
        super(sqlEle, params, cs);
    }

    /**
     * 当SQLEle中的ParamEle对象为null时，即在xml文件中没param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @throws NullPointerException 假如参数sqlEle或params为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, List<Object> params) {
        super(sqlEle, params);
    }

    /**
     * 当SQLEle中的ParamEle对象为null时，即在xml文件中没param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle) {
        super(sqlEle);
    }

    /**
     * 当SQLEle中的ParamEle对象为null时，即在xml文件中没param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param cs     实体类型
     * @throws NullPointerException 假如参数cs或sqlEle为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, Class<?> cs) {
        super(sqlEle, cs);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param map    map预处理参数(可为null)
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, Map<String, Object> map, T obj) throws XmlSQLException {
        super(sqlEle, map, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param cs     实体类型
     * @param map    map预处理参数(可为null)
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, Class<?> cs, Map<String, Object> map, T obj) throws XmlSQLException {
        super(sqlEle, cs, map, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param cs     实体类型
     * @param map    map预处理参数(可为null)
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, List<Object> params, Class<?> cs, Map<String, Object> map, T obj) throws XmlSQLException {
        super(sqlEle, params, cs, map, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param cs     实体类型
     * @param map    map预处理参数(可为null)
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, Object[] params, Class<?> cs, Map<String, Object> map, T obj) throws XmlSQLException {
        super(sqlEle, params, cs, map, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param cs     实体类型
     * @param map    map预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, Object[] params, Class<?> cs, Map<String, Object> map) throws XmlSQLException {
        super(sqlEle, params, cs, map);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param cs     实体类型
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, Object[] params, Class<?> cs, T obj) throws XmlSQLException {
        super(sqlEle, params, cs, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param map    map预处理参数(可为null)
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, Object[] params, Map<String, Object> map, T obj) throws XmlSQLException {
        super(sqlEle, params, map, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param params 预处理参数
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, Object[] params, T obj) throws XmlSQLException {
        super(sqlEle, params, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param map    map预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, Map<String, Object> map) throws XmlSQLException {
        super(sqlEle, map);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, T obj) throws XmlSQLException {
        super(sqlEle, obj);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param cs     实体类型
     * @param map    map预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public XmlSQLForOracle(SQLEle sqlEle, Class<?> cs, Map<String, Object> map) throws XmlSQLException {
        super(sqlEle, cs, map);
    }

    /**
     * 当SQLEle中的ParamEle对象不为null时，即在xml文件中有param元素时，使用该构造函数
     *
     * @param sqlEle SQLEle对象
     * @param cs     实体类型
     * @param obj    对象预处理参数(可为null)
     * @throws XmlSQLException      假如SQL语句解析出错，抛出该异常
     * @throws NullPointerException 假如参数sqlEle为null，抛出该异常
     */
    public <T> XmlSQLForOracle(SQLEle sqlEle, Class<?> cs, T obj) throws XmlSQLException {
        super(sqlEle, cs, obj);
    }

    /**
     * 获取总数据条数SQL对象
     *
     * @return
     */
    @Override
    public Statistics countSql() {
        return null;
    }

    /**
     * 设置分页信息
     *
     * @param limit
     */
    @Override
    public void setLimit(Limit limit) {
        this.limit = limit;
    }

    /**
     * 获取分页信息
     *
     * @return
     */
    @Override
    public Limit getLimit() {
        return limit;
    }

    @Override
    public String getParamSql() {
        String sql = super.getParamSql();
        if (limit == null) return sql;

        sql = "(" + sql + ") tt_";
        sql = "(select tt_.*, rownum rn_ from " + sql + ")";
        sql = "select * from " + sql;
        sql += " where rn_ between ? and ?";
        return sql;
    }

    @Override
    public Object[] getParams() {
        Object[] values = super.getParams();
        if (limit != null) {
            int length = values.length;
            values = Arrays.copyOf(values, length + 2);
            values[length] = limit.getStartPos() + 1;
            values[length +1] = limit.getStartPos() + limit.getResultCount();
        }
        return values;
    }

    @Override
    public String getSql() {
        StringBuilder sb = new StringBuilder(getParamSql());
        return SQLUtil.fillWithParams(sb, getParams());
    }
}
